/**
 * 
 */
package hu.rsc.feeds.client.gui.table2;

import hu.rsc.feeds.client.data.ColumnFilterInfo;
import hu.rsc.feeds.client.data.Dictionary;
import hu.rsc.feeds.client.util.ImageResources;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.gen2.table.client.AbstractColumnDefinition;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.ToggleButton;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;

/**
 * @author Gyuri
 * 
 */
public abstract class AdvancedAbstractColumnDefinition<RowType, ColType> extends AbstractColumnDefinition<RowType, ColType> {

    public static final int MODE_ONLY_COLUMNNAME = 0;
    public static final int MODE_FILTER_AND_SORT = 1;
    public static final int MODE_FILTER = 2;
    public static final int MODE_SORT = 3;

    private Image ascendingImage = new Image(ImageResources.SORT_ASCENDING);
    private Image descendingImage = new Image(ImageResources.SORT_DESCENDING);
    private Image filterButtonImage = new Image(ImageResources.FILTER_PLUS_ENABLED);
    private Image filterActiveButtonImage = new Image(ImageResources.FILTER_MINUS_ENABLED);

    private String columnName;
    private int column;
    private FilterChangeListener tableModel;
    private FilterChangeListener tableHolderComponent;
    // itt kell létrehozni a textboxokat, hogy tudjuk őket később
    // törölni/felölteni
    private TextBox filterTextBox1 = new TextBox();
    private TextBox filterTextBox2 = new TextBox();
    private Image resetFilterButtonImage = new Image("images/btn_filter_reset.png");
    private ToggleButton filterButton;
    private HorizontalPanel sortIndicatorPanel;
    private boolean filtered = false;
    private int mode;

    public AdvancedAbstractColumnDefinition(String columnName, int column, FilterChangeListener tableModel, FilterChangeListener filterChangeListener) {
	this(columnName, column, tableModel, filterChangeListener, AdvancedAbstractColumnDefinition.MODE_FILTER_AND_SORT);
    }

    public AdvancedAbstractColumnDefinition(String columnName, int column, FilterChangeListener tableModel, FilterChangeListener filterChangeListener, int mode) {
	this.columnName = columnName;
	this.column = column;
	this.tableModel = tableModel;
	this.tableHolderComponent = filterChangeListener;

	this.mode = mode;

	Widget headerWidget = this.getHeaderWidget();

	if (headerWidget instanceof HasHorizontalAlignment) {
	    ((HasHorizontalAlignment) headerWidget).setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
	}

	this.setHeader(0, headerWidget);

	this.setHeaderTruncatable(true);
    }

    public void applySortingIndicator(boolean ascending) {
	if (ascending) {
	    this.sortIndicatorPanel.add(this.ascendingImage);
	} else {
	    this.sortIndicatorPanel.add(this.descendingImage);
	}
    }

    public void clearSortIndicator() {
	if (this.sortIndicatorPanel != null) {
	    this.sortIndicatorPanel.clear();
	}
    }

    public Widget getHeaderWidget() {
	if (this.mode == AdvancedAbstractColumnDefinition.MODE_ONLY_COLUMNNAME) {
	    Label columnNameLabel = new Label(this.columnName);
	    columnNameLabel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
	    return columnNameLabel;
	}

	HorizontalPanel widgetRoot = new HorizontalPanel();
	widgetRoot.addStyleName("headerWidget");
	widgetRoot.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);

	switch (this.mode) {
	case MODE_FILTER: {
	    this.addColumnName(widgetRoot);
	    this.addFilterPanel(widgetRoot);
	    break;
	}
	case MODE_SORT: {
	    this.addSortIndicatorPanel(widgetRoot);
	    this.addColumnName(widgetRoot);
	    break;
	}
	case MODE_FILTER_AND_SORT: {
	    this.addSortIndicatorPanel(widgetRoot);
	    this.addColumnName(widgetRoot);
	    this.addFilterPanel(widgetRoot);
	    break;
	}

	default: {
	    throw new RuntimeException("Hibás columndefinition!");
	}
	}

	widgetRoot.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);

	return widgetRoot;
    }

    private void addColumnName(HorizontalPanel widgetRoot) {
	HTML columnNameHTML = new HTML(this.columnName);
	// Ez nem kell, ez miatt nem volt középen:
	// columnNameHTML.setHeight("22px");
	widgetRoot.add(columnNameHTML);
    }

    private void addFilterPanel(HorizontalPanel widgetRoot) {
	// filteres gombok
	HorizontalPanel filterPanel = new HorizontalPanel();
	filterPanel.setSize("30px", "16px");
	filterPanel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
	filterPanel.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);

	this.filterButton = this.initFilterButton();
	filterPanel.add(this.filterButton);

	// PushButton resetFilterButton = this.initResetFilterButton();
	// filterPanel.add(resetFilterButton);

	widgetRoot.add(filterPanel);
	widgetRoot.setCellHeight(filterPanel, "16px");
	widgetRoot.setCellHorizontalAlignment(filterPanel, HasHorizontalAlignment.ALIGN_RIGHT);
    }

    private void addSortIndicatorPanel(HorizontalPanel widgetRoot) {
	this.sortIndicatorPanel = new HorizontalPanel();
	this.sortIndicatorPanel.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);
	//		this.sortIndicatorPanel.setSize("20px", "20px");
	widgetRoot.add(this.sortIndicatorPanel);
    }

    private DialogBox createDialogBox(boolean withDeleteFilterButton) {
	// Create a dialog box and set the caption text
	final DialogBox dialogBox = new DialogBox();
	dialogBox.ensureDebugId("filterDialogBox");
	dialogBox.setText(Dictionary.getEntry(Dictionary.TITLE_FILTER, dialogBox));

	final TextBox filterTextBox;
	if (withDeleteFilterButton) {
	    filterTextBox = this.filterTextBox1;
	} else {
	    filterTextBox = this.filterTextBox2;
	}
	filterTextBox.setWidth("95%");

	filterTextBox.addKeyPressHandler(new KeyPressHandler() {

	    @Override
	    public void onKeyPress(KeyPressEvent kpe) {
		if (kpe.getCharCode() == '\r') {
		    AdvancedAbstractColumnDefinition.this.doFilter(filterTextBox.getText(), dialogBox);
		}
	    }
	});

	Button doFilterButton = new Button();
	doFilterButton.setText(Dictionary.getEntry(Dictionary.BUTTON_FILTER, null));
	doFilterButton.addStyleName("dialogButton");
	doFilterButton.addClickHandler(new ClickHandler() {

	    @Override
	    public void onClick(ClickEvent arg0) {
		AdvancedAbstractColumnDefinition.this.doFilter(filterTextBox.getText(), dialogBox);
	    }
	});
	Button doCancelButton = new Button();
	doCancelButton.setText(Dictionary.getEntry(Dictionary.BUTTON_FILTER_CANCEL, null));
	doCancelButton.addStyleName("dialogButton");
	doCancelButton.addClickHandler(new ClickHandler() {
	    @Override
	    public void onClick(ClickEvent arg0) {
		dialogBox.hide();
	    }
	});
	Button deleteFilterButton = new Button();
	deleteFilterButton.setText(Dictionary.getEntry(Dictionary.BUTTON_FILTER_DELETE, null));
	deleteFilterButton.addStyleName("dialogButton");
	deleteFilterButton.addClickHandler(new ClickHandler() {
	    @Override
	    public void onClick(ClickEvent arg0) {
		// ha null értékkel küljük, akkor a listből törlődik
		ColumnFilterInfo info = new ColumnFilterInfo(AdvancedAbstractColumnDefinition.this.column, null);
		// átt kell adnunk a tablemodelnek az infot
		// ez a lekérdezéshez kell
		AdvancedAbstractColumnDefinition.this.tableModel.listenForFilterChange(info);
		// a filterinfolistet át kell adnunk a főoldalnak pl
		// AdminUser-nek, és refresh()-t kell hívnunk ott rajta
		// ez a counthoz kell
		AdvancedAbstractColumnDefinition.this.tableHolderComponent.listenForFilterChange(info);
		AdvancedAbstractColumnDefinition.this.filterButton.setTitle(null);
		// beállítjuk mind2 texboxot
		AdvancedAbstractColumnDefinition.this.filterTextBox1.setText(null);
		AdvancedAbstractColumnDefinition.this.filterTextBox2.setText(null);
		AdvancedAbstractColumnDefinition.this.filtered = false;
		//AdvancedAbstractColumnDefinition.this.filterButton.getUpFace().setImage(AdvancedAbstractColumnDefinition.this.filterButtonImage);
		dialogBox.hide();
	    }
	});
	HorizontalPanel horizontalPanel = new HorizontalPanel();
	horizontalPanel.addStyleName("dialogButtonPanel");
	// horizontalPanel.addStyleName("columnTextFilter");
	horizontalPanel.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);
	horizontalPanel.add(doFilterButton);
	if (withDeleteFilterButton) {
	    horizontalPanel.add(deleteFilterButton);
	}
	horizontalPanel.add(doCancelButton);
	horizontalPanel.setSpacing(2);

	VerticalPanel verticalPanel = new VerticalPanel();
	verticalPanel.add(filterTextBox);
	verticalPanel.setCellWidth(filterTextBox, "100%");
	verticalPanel.add(horizontalPanel);
	dialogBox.setWidget(verticalPanel);
	// Return the dialog box
	return dialogBox;
    }

    private ToggleButton initFilterButton() {
	final DialogBox dialogBox = this.createDialogBox(false);
	dialogBox.setGlassEnabled(true);
	dialogBox.setAnimationEnabled(true);
	// dialog box a filter kikapcsolásához
	final DialogBox dialogBoxWithStop = this.createDialogBox(true);
	dialogBoxWithStop.setGlassEnabled(true);
	dialogBoxWithStop.setAnimationEnabled(true);

	ToggleButton button = new ToggleButton(this.filterButtonImage);
	button.setStyleName("uta-imageButton");
	button.addClickHandler(new ClickHandler() {
	    @Override
	    public void onClick(ClickEvent sender) {
		if (!AdvancedAbstractColumnDefinition.this.filtered) {
		    dialogBox.center();
		    AdvancedAbstractColumnDefinition.this.filterTextBox2.setFocus(true);
		} else {
		    dialogBoxWithStop.center();
		    AdvancedAbstractColumnDefinition.this.filterTextBox1.setFocus(true);
		}
	    }
	});
	return button;
    }

    // private PushButton initResetFilterButton() {
    // PushButton button = new PushButton(this.resetFilterButtonImage);
    // button.setStyleName("uta-imageButton");
    // button.addClickHandler(new ClickHandler() {
    // @Override
    // public void onClick(ClickEvent arg0) {
    // // ha null értékkel küljük, akkor a listből törlődik
    // ColumnFilterInfo info = new ColumnFilterInfo(
    // AdvancedAbstractColumnDefinition.this.column, null);
    // // átt kell adnunk a tablemodelnek az infot
    // // ez a lekérdezéshez kell
    // AdvancedAbstractColumnDefinition.this.tableModel
    // .listenForFilterChange(info);
    // // a filterinfolistet át kell adnunk a főoldalnak pl
    // // AdminUser-nek, és refresh()-t kell hívnunk ott rajta
    // // ez a counthoz kell
    // AdvancedAbstractColumnDefinition.this.tableHolderComponent
    // .listenForFilterChange(info);
    // AdvancedAbstractColumnDefinition.this.filterButton
    // .setTitle(null);
    // // beállítjuk mind2 texboxot
    // AdvancedAbstractColumnDefinition.this.filterTextBox1
    // .setText(null);
    // AdvancedAbstractColumnDefinition.this.filterTextBox2
    // .setText(null);
    // AdvancedAbstractColumnDefinition.this.filtered = false;
    // AdvancedAbstractColumnDefinition.this.filterButton
    // .getUpFace()
    // .setImage(
    // AdvancedAbstractColumnDefinition.this.filterButtonImage);
    // }
    // });
    // return button;
    // }

    protected void doFilter(String filterText, DialogBox dialogBox) {
	ColumnFilterInfo info = new ColumnFilterInfo(AdvancedAbstractColumnDefinition.this.column, filterText);
	// átt kell adnunk a tablemodelnek az infot
	// ez a lekérdezéshez kell
	AdvancedAbstractColumnDefinition.this.tableModel.listenForFilterChange(info);
	// a filterinfolistet át kell adnunk a főoldalnak pl
	// AdminUser-nek, és refresh()-t kell hívnunk ott rajta
	// ez a counthoz kell
	AdvancedAbstractColumnDefinition.this.tableHolderComponent.listenForFilterChange(info);
	// tooltip
	AdvancedAbstractColumnDefinition.this.filterButton.setTitle(filterText);
	// beállítjuk mind2 texboxot
	AdvancedAbstractColumnDefinition.this.filterTextBox1.setText(filterText);
	AdvancedAbstractColumnDefinition.this.filterTextBox2.setText(filterText);
	AdvancedAbstractColumnDefinition.this.filtered = true;
	AdvancedAbstractColumnDefinition.this.filterButton.getUpFace().setImage(AdvancedAbstractColumnDefinition.this.filterActiveButtonImage);
	dialogBox.hide();
    }
}
